package com.foreveross.taskservice.application.impl.task.service;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.foreveross.taskservice.application.channel.IGradChannelApplication;
import com.foreveross.taskservice.application.impl.BaseJpaApplicationImpl;
import com.foreveross.taskservice.application.impl.convert.AirFreightChannelConvert;
import com.foreveross.taskservice.application.impl.convert.AirFreightTaskConvert;
import com.foreveross.taskservice.application.task.service.IBuildTaskQueueLogApplication;
import com.foreveross.taskservice.application.task.service.IBuildTaskToCacheApplication;
import com.foreveross.taskservice.application.task.service.ITaskTemplateApplication;
import com.foreveross.taskservice.common.CacheDataSpace;
import com.foreveross.taskservice.common.TaskStatusEnum;
import com.foreveross.taskservice.common.model.AbstractTaskModel;
import com.foreveross.taskservice.common.model.airfreight.AirFreightChannelModel;
import com.foreveross.taskservice.common.model.airfreight.AirFreightTaskModel;
import com.foreveross.taskservice.core.domain.channel.GradChannelEntity;
import com.foreveross.taskservice.core.domain.task.TaskQueueRecordEntity;
import com.foreveross.taskservice.core.domain.task.TaskTemplateEntity;
import com.foreveross.taskservice.infra.util.DateUtil;
import com.foreveross.taskservice.taskcache.ITaskCacheQuery;
import com.foreveross.taskservice.taskcache.ITaskCacheStorage;
import com.google.common.collect.Sets;
@Service
@Transactional
public class BuildTaskToCacheApplicationImpl extends BaseJpaApplicationImpl
		implements IBuildTaskToCacheApplication {
	@Resource(name="gradChannelApplicationImpl")
	private IGradChannelApplication gradChannelApplication;
	@Resource(name = "taskTemplateApplicationImpl")
	private ITaskTemplateApplication taskTemplateApplication;
	@Resource(name = "buildTaskQueueLogApplicationImpl")
	private IBuildTaskQueueLogApplication buildTaskQueueLogApplication;
	@Resource(name="redisTaskCacheStorageImpl")
	private ITaskCacheStorage taskCacheStorage;
	@Resource(name="redisTaskCacheQueryImpl")
	private ITaskCacheQuery taskCacheQuery;
	
	private Logger log=Logger.getLogger(BuildTaskToCacheApplicationImpl.class);
	
	
	private int updateAndToCache(List<TaskTemplateEntity> templates,GradChannelEntity channel)throws Exception{
		int size = 0;
		if(templates!=null && !templates.isEmpty()){
			List<TaskQueueRecordEntity> logs;
			for (TaskTemplateEntity temp : templates) {
				if(!this.filterTask(temp)){
					temp.setStatus(0);//标记成不可用
					taskTemplateApplication.save(temp);
					log.info(String.format("任务模版[%s]信息不全，跳过此条模版,且关闭模版", temp.getId()));
					continue;
				}
				logs = buildTaskQueueLogApplication.buildTaskQueueRecords(temp);
				log.info(String.format("以模板创建的任务数量%s", logs != null ? logs.size() : 0));
				if (logs != null && !logs.isEmpty()) {
					List<AirFreightTaskModel> taskModels=AirFreightTaskConvert.convertEntity2Model(logs);
					AirFreightChannelModel channelModel=AirFreightChannelConvert.convert(channel);
					LinkedHashSet<AbstractTaskModel> set=Sets.newLinkedHashSet();
					for(AirFreightTaskModel tm:taskModels){
						tm.setChannel(channelModel);
						tm.setUseProxyip(channel.getUseProxyIp()==1);//是否使用代理IP
						set.add(tm);
					}
					// 将任务放入cacahe
					taskCacheStorage.addTasks(set);
					// 更新模版
					temp.setNextGrabTime(DateUtil.addTime(temp.getNextGrabTime(), temp.getFrequency()*60*1000));
					taskTemplateApplication.save(temp);
					size += logs.size();
				}
			}
		}
		return size;
	}
	
	private int updateAndToCache(TaskTemplateEntity template,GradChannelEntity channel)throws Exception{
		List<TaskTemplateEntity> temps=new ArrayList<TaskTemplateEntity>();
		temps.add(template);
		return updateAndToCache(temps,channel);
	}
	private boolean filterTask(TaskTemplateEntity taskInfo) {
		// 起飞城市 ，目的城市 ，hbasekey业务编码，区域都不能为空，否则该条任务没有意义
		// 这里不再通过现有信息去获取其它信息，以使任务记录有效
		if (StringUtils.isNotBlank(taskInfo.getFromCity())
				&& StringUtils.isNotBlank(taskInfo.getToCity())
				&& StringUtils.isNotBlank(taskInfo.getAttachHbaseKey())
				/*&& StringUtils.isNotBlank(taskInfo.getAreaCode())*/ //2014-03-19 现在区域码可以忽略了 
				&& taskInfo.getGrabChannelId() != null) {
			return true;
		}
		return false;
	}

	@Override
	public int buildTaskToCache(
			int templateMaxSize, String channelCode, long maxCacheTaskSize)
			throws Exception {
		int size=0;
		//如果队列中等待数量超出最大值，不进行任务生成
		long currentWaitSize = taskCacheQuery.queryTaskSize(CacheDataSpace.AirFreightSpace(),channelCode,TaskStatusEnum.TASK_WATI);
		if(currentWaitSize >= maxCacheTaskSize){
			log.info(String.format("渠道[%s]当前等待任务数为[%s],允许的最大等待任务数为[%s]",channelCode, currentWaitSize, maxCacheTaskSize));
			return size;
		}
		GradChannelEntity gradChannel=gradChannelApplication.get(channelCode);
		List<TaskTemplateEntity> temps = null;
		try{
			temps = taskTemplateApplication.getTaskTemplatesOrderPriorityDesc(templateMaxSize,channelCode);
			log.info(String.format("获得的模板数量%s", temps != null ? temps.size() : 0));
			for(TaskTemplateEntity t:temps){
				//将优先级高于内存中的任务的模版创建到cache中
				size+=updateAndToCache(t,gradChannel);
				if((size+currentWaitSize) >= maxCacheTaskSize){
					break;
				}
			}
		}finally{
			temps = null;
			gradChannel = null;
		}
		return size;
	}
	
	
	
}
